# Copyright 2001-2007 by iNeed,Inc. All Rights Reserved.
#-*- encoding:utf-8 -*-
"""
The gloabal settings of the project

"""
from __future__ import division
import sys, os, time,socket,re,random
import unittest,logging
import threading
import math,configall

__author__  = "Number Huang<huang.bafeng@iNeed.com>"
__status__  = "developing"
__version__ = "0.1108.29.1"


LOGDEBUG2 = 5
def getUStr(str1):
    return eval('u"'+unicode(str1)+'"')

logging.addLevelName(LOGDEBUG2, "DEBUG2")
def getLogger(name,filePath):

    formatter = logging.Formatter('%(asctime)s: %(module)s.%(funcName)s.%(lineno)d-> %(message)s')
    console = logging.StreamHandler()
    console.setFormatter(formatter)
    #console.setLevel(logging.DEBUG)

    formatter = logging.Formatter('%(asctime)s: %(levelname)s-%(module)s.%(funcName)s.%(lineno)d-> %(message)s')
    fileHandler = logging.FileHandler(filename=filePath,mode='w')
    fileHandler.setFormatter(formatter)
    #fileHandler.setLevel(LOGDEBUG2)

    #logging.getLogger('').addHandler(console)#LoggerAdapter(logging.getLogger("iNeedTaxi"),{"ip" : "msgCenter"})
    logger = logging.getLogger(name)
    logger.addHandler(console)
    logger.addHandler(fileHandler)
    logger.setLevel(LOGDEBUG2)

    return logger

filterLog=("SQLITE3","NOTIFYRequester",)
def FilterLog1(info):
    if info:
        for log in filterLog:
            if info.find(log)>=0:
                return None
    return info
class AutoLock(object):
    """
        A RAII lock wrapper
    """

    def __init__(self,owner,lock,info=None):
        
       
        self.info = FilterLog1(info)
       
        self.lock = lock
        self.log = owner.log
    def __enter__(self):

        if self.info: self.log.log(LOGDEBUG2,"@!enter %s",self.info)
        self.lock.acquire()

    def __exit__(self, except_type, except_obj, traceback):

        self.lock.release()
        if self.info: self.log.log(LOGDEBUG2,"@!exit %s",self.info)

        return not except_type

class AutoEntryLog(object):
    """
         A RAII comment wrapper
    """

    def __init__(self,owner,info):

        self.info = info
        self.log  = owner.log
    def __enter__(self):

        self.log.log(3,"@!enter %s",self.info)

    def __exit__(self, except_type, except_obj, traceback):

        self.log.log(3,"@!exit %s",self.info)
        return not except_type

ETS_BUSY = 1
ETS_IDLE = 0

class TaskEngineFactory(object):
    """
        for server,the derived factory is necessary , and for client,just use the base factory,
        which only maintains two engine, taskEngine and msgEngine
        It is still a prototype for extention in future.
    """

    def __init__(self,owner):

        self.engineList=[]
        self.engine1 = None
        self.engine2 = None
        self.owner = owner

    def exit(self):
        for engine in self.engineList:
            engine.exit()

    def getOneEngine(self,name,isLongDurationTask=False):
        """
        this method is for possible load balance in future,currently, just return the one
        TDTO:
            add more params,like urgency,duration,frequency
        """
        if not isLongDurationTask:
            if not self.engine1:
                self.engine1=TaskEngine(self.owner,name)
                self.engineList.append(self.engine1)
            return self.engine1
        else:
            if not self.engine2:
                self.engine2=TaskEngine(self.owner,name)
                self.engineList.append(self.engine2)
            return self.engine2
ALWAYS_RUN=-1
class TaskEngine(threading.Thread):
    """
        A taskEngine is a warpper of thread, and acts as a task scheduler.
    """

    def __init__(self,owner,name="TaskEngine",hang=False):

        self.log= owner.log
        super(TaskEngine,self).__init__()
        self.taskList= []
        self.forceExit = False
        self.lock= threading.Condition()
        self.name = name
        self.status = ETS_IDLE
        if not hang:
            self.start()

    def exit(self):
        self.forceExit = True
        time.sleep(0.01)

        self.deleteAll()


    def _findRunnableTask(self):

        with AutoLock(self,self.lock):
            for task in self.taskList:
                if task.time2Run():
                    return task
                elif task.isLoopEnd():
                    self.deleteTask(task)
        return None

    def getStatus(self):
        return self.status

    def run(self):

       with AutoEntryLog(self,self.name):
         while not self.forceExit :
                time.sleep(0.001)

                task = self._findRunnableTask()
                try:
                     if task:
                          self.status = ETS_BUSY
                          task.run()
                          #self.log.debug("run task:%s"%task.name)
                          task.reset()

                     self.removeUnUsedTask()

                except:
                    self.log.exception("Task(%s) exception,go on next Task"%(task.name))
                    self.deleteTask(task)
                self.status = ETS_IDLE


    def addTask(self,task,session=None):
         with AutoLock(self,self.lock,"add task_%s"%task.name):
            if task not in self.taskList:
               self.taskList.append(task)
               if session and task not in session.taskList:
                    session.taskList.append((self,task))

    def removeUnUsedTask(self):
         with AutoLock(self,self.lock):
             for task in self.taskList:
                if task.isLoopEnd():
                    self.deleteTask(task)

    def deleteTask(self,task):
        with AutoLock(self,self.lock,"removing task_%s"%task.name):
                if task in  self.taskList:#it is possible that the task is reomved repeatly
                    self.taskList.remove(task)

    def deleteAll(self):
        with AutoLock(self,self.lock,"delete all task"):
            for task in self.taskList:
                self.deleteTask(task)

class Task(object):
    """
        class comment
    """

    def __init__(self,owner,name,timeIntervalBySec,loopCount=1,initTime=0):

        self.name = name
        
        self.log= owner.log
        self.reSchedule(timeIntervalBySec, loopCount, initTime)
        if FilterLog1(name):
            self.log.debug("CreateTask_%s: loopCount=%d,interval=%f"%(name,loopCount,timeIntervalBySec))
    def exit(self):
        self.loopCount = 0

    def run(self):
         raise Exception,'unimplemented run'

    def reSchedule(self,timeIntervalBySec,loopCount=1,initTime=0):
        """
        to change the interval to a bigger value is a simple way to postpone the task
        """
        self.interval   = timeIntervalBySec
        if initTime:
            self.lastTime = initTime
        else:
            self.lastTime = time.time()
        self.loopCount  = loopCount

    def time2Run(self):

        ready = 0
        if(self.loopCount):
             curTime    = time.time()
             if (curTime - self.lastTime > self.interval):
                ready = 1
        return ready

    def reset(self):
        
        if(self.loopCount>0):
            self.loopCount -= 1
        self.lastTime    = time.time()

    def isLoopEnd(self):
            
        return self.loopCount==0


class Reporter(object):
    """
    This class plays the callback function role for requester.
    It is the most important communication mechanism to get the result from the callee in a async way.
    The only interface is the Notify and any subclass can overwride it.
    And it uses the chain responsibility pattern, propagates the info along the owner path
    It is also used in sync mode.
    """

    def __init__(self,owner,callback=None,timeout=10,async=True,extraParam=None):
        """
        @type owner: a Reporter to propagate the result
        @type callback: a function whose signature compliant to the notify
                        callback may be None, in which case, the selft.result is set the retCode and retInfo.
        @type timeout: tells the callee, the call should be done in the timeout setting
                        It uses the owner setting first if have.
        @type async: True by default, if False, the callee needs to  do something in a polling way
                      It uses the owner setting first if have.
        """
        self.owner = owner
        self.callback = callback
        if not self.owner:
            self.async   = async
            self.timeout = timeout
        else:
            self.async   = self.owner.async
            self.timeout = self.owner.timeout
        self.result = None
        self.extraParam = extraParam
        
    def notify(self,retCode,retInfo,extraInfo=None):
        """
        @type retCode: defined in EN_XXX in
        @type retInfo: retCodeMap[retCode], it also can be set with any string
        @type extraInfo: a dictionary for additional info, which is context dependent,
                        be careful to check the caller and callee.

        """
        #retCode = int(retCode)
        if self.callback:
            if extraInfo:
                if self.extraParam:
                   self.extraParam.update(extraInfo)
                else:
                   self.extraParam = extraInfo
            self.callback(retCode,retInfo,self.extraParam)
        else:
            self.result = (retCode,retInfo)
        #And it uses the chain responsibiity pattern, propogate the info along the owner path
        if self.owner:
            self.owner.notify(retCode,retInfo,extraInfo)

NonReporter = Reporter(None) #this used for Null Object pattern

class SyncNonReporter(Reporter):
    """
    Do nothing but wait for the result in the timeout
    """
    def __init__(self,timeout1=10):
        super(SyncNonReporter,self).__init__(None,timeout=timeout1,async=False)
        
class FakeOwner(object):
    """
    the abstract interface between  top UI and peer.
    """
    def __init__(self):
        self.log = logging
        
    def handleRequest(self,method,infoDict,extraInfoDict,reporter):
        """
        @type method: the method of the message
        @type info: the detailed message info in the dict manner
        @type extraInfoDict: additional info, the CSTR2_TIMEOUT must be there
        @type reporter: 
        """





centerID="hxy20100114"
centerAddr=("127.0.0.1",4032)
driverAddr=("127.0.0.1",4062)
passengerAddr=("127.0.0.1",4081)
centerFirstSession = 3000
driverFirstSession = 2000
passengerFirstSession = 1000

portRange=(3000,6000)

def getCurGMT(t=None):

    if t==None:
        t = time.gmtime()
    return time.strftime('%a, %d %b %Y %H:%M:%S GMT',t)

localtimeFmt = '%Y-%m-%d %H:%M:%S' #'%a, %d %b %Y %H:%M:%S'
def getLocalTime(t=None):

    t = time.localtime(t)

    return time.strftime(localtimeFmt,t)

def transD2C(number):
    if 0:#number==10:
        return d2CMAPPING1[10]
    else:
        C1 = int(number/10)
        C2 = number%10
        if C1:
           if C1==1:
                C1=d2CMAPPING1[10]
           else:
                C1=d2CMAPPING1[C1]+d2CMAPPING1[10]
        else:
           C1=""
        if C2:
           C2=d2CMAPPING1[C2] 
        else:
           C2=""
        ret = C1+C2
        if not ret:
            return d2CMAPPING1[0]
        else:
            return C1+C2

getHMPattern=re.compile(r"(\d+)-(\d+)-(\d+)")
d2CMAPPING1 = (u'零', u'一', u'二', u'三', u'四', u'五', u'六', u'七', u'八', u'九',u"十",)
def translateTimeC(t):
    curTime = time.localtime(None) 
    t =  time.localtime(t)
    m = getHMPattern.search(time.strftime("%j-%H-%M",t))
    if m:
        day     = int(m.group(1))
        hour    = int(m.group(2))
        minute  = int(m.group(3))
        value = day - int(time.strftime("%j",curTime))
        if value==1:
            day = u"明天"
        else:
            day = u"今天"
        if hour>12:
           if hour>18:
               noon=u"晚上"
           else:
               noon=u"下午"
           hour -= 12
        else:
           if hour<6:
               noon=u"凌晨"
           else:
               noon=u"上午"
        hour  =transD2C(hour)+u"点"
        minute=transD2C(minute)+u"分"  
   
        return day+noon + hour + minute
#the following are for utest
def testSingleMethod(cls,method):
    suite = unittest.TestSuite()
    suite.addTest(cls(method))
    run_test(suite)

def testWholeClass(cls):
    suite = unittest.TestLoader().loadTestsFromTestCase(cls)
    run_test(suite)

def run_test(suite):
    testRunner = unittest.TextTestRunner()
    testRunner.run(suite)



#peer common status
ES_UNLOGGED     = 0
ES_IDLE         = 1 #logged in but is not processing order
ES_BUSY         = 2 #isProcessing an order
ES_UNAVAILABLE  = 3 #for driver,can not accept order
#ES_AVAILABLE    = 4 #for driver,can accept order,for pooling,it is True even in executing an order
#passenger status



EPR_DRIVER      = 0
EPR_PASSENGER   = 1
locationTable=("driverstatus","passengerstatus")
#service type
EST_OFFERING    = 16    #for driver
EST_BOOKING     = 1     #only booking
EST_POOLING     = 2     #only pooling
EST_BPEITHER    = 3     #booking or pooling



"""
service status at server side (database)
"""
ESS_PUBLISHED   = 2
ESS_MATCHING    = 3
ESS_CONFIRMED   = 4

"""
The following is the subStatus of one service
WF: wait_for
WFR: wait_for_response_
"""


ESS_NONE        = 9     #undefined status
ESS_CLOSED      = 10
ESE_BENCH       = ESS_CLOSED
ESE_WFR_PUBLISH = ESE_BENCH + 1
ESE_WF_ORDER = ESE_BENCH + 2
ESE_WFR_CD = ESE_BENCH + 3
ESE_ORDER_DONE = ESE_BENCH + 4

ESE_GOFOR_PICKUP = ESE_BENCH + 5
ESE_READY_PICKUP = ESE_BENCH + 6 
ESE_TRANSATION_GOING = ESE_BENCH + 7
ESE_TRANSATION_DONE = ESE_BENCH + 8


ESE_READY_BORDING = ESE_BENCH + 9
ESE_WFR_BT  =ESE_BENCH + 10
ESE_WFR_ET  =ESE_BENCH + 11
ESE_READY_ET=ESE_BENCH + 12 #for test, notify the passenger to ET
ESE_READY_BT=ESE_BENCH + 13
ESE_WFR_RB  =ESE_BENCH + 14

ESE_WF_GUI_CO = ESE_BENCH +21
ESE_WF_GUI_CA = ESE_BENCH +22
ESE_WF_GUI_CD = ESE_BENCH +23
ESE_WF_GUI_TOGD = ESE_BENCH +24
ESE_WF_GUI_ERROR = ESE_BENCH +25
ESE_WF_GUI_UDS = ESE_BENCH +26
ESE_WF_GUI_BT = ESE_BENCH +27
ESE_WF_GUI_ET = ESE_BENCH +28
ESE_WF_GUI_RB = ESE_BENCH +29
"""
order STATUS
"""

EOS_CREATED     = 0
EOS_EXECUTING   = 1
EOS_CLOSED      = 2
"""
FSM table of service
If the service is in ESS_PROCESSING, set the peer status to processing
"""
FSMTable={
#ES_XX is peer status,also list here for unified process, because the service status is also the subStatus of ES_BUSY
ES_UNLOGGED:      (ESS_NONE,       ESS_NONE,    "ES_UNLOGGED", u"未登录"), 
ES_IDLE:          (ESS_NONE,       ESS_NONE,    "ES_IDLE", u"空闲"), 
ES_BUSY:          (ESS_NONE,       ESS_NONE,    "ES_BUSY", u"处理中"), 
ES_UNAVAILABLE:   (ESS_NONE,       ESS_NONE,    "ES_UNAVAILABLE", u"不可行"),
#the NONE and close are begin and end of the subStatus of the service     
ESS_NONE         :  (ESS_NONE,       ESS_NONE,    "ESS_NONE", u"无"), #makes no sense        
ESS_CLOSED:         (ESS_NONE,              ESS_NONE,           "ESS_CLOSED", u"关闭"),#makes no sense        
#for passenger
ESE_WFR_PUBLISH:    (ESE_WF_ORDER,          ESS_CLOSED,         "ESE_WFR_PUBLISH", u"发布中"),         #handleResponse
ESE_WF_ORDER:       (ESS_NONE,              ESS_NONE,           "ESE_WF_ORDER", u"预订中"),      #handleRequest
ESE_WF_GUI_CO:      (ESE_ORDER_DONE,        ESS_CLOSED,         "ESE_WF_GUI_CO", u"等待确认订单"), #handleNotifyOnUI
ESE_WFR_CD:         (ESE_ORDER_DONE,        ESS_CLOSED,         "ESE_WFR_CD", u"等待司机确认"), #handleResponse
ESE_READY_BORDING:  (ESE_READY_BORDING,     ESE_READY_BORDING,  "ESE_READY_BORDING", u"车已到达"),
ESE_WFR_BT:         (ESE_TRANSATION_GOING,  ESS_CLOSED,         "ESE_WFR_BT", u"等待确认交易开始"),
ESE_WFR_ET:         (ESE_TRANSATION_DONE,   ESS_CLOSED,         "ESE_WFR_ET", u"等待确认交易完成"),
ESE_WF_GUI_TOGD:    (ESE_WFR_PUBLISH,       ESS_CLOSED,         "ESE_WF_GUI_TOGD", u"无可用出租车"),
ESE_WF_GUI_RB:      (ESE_TRANSATION_GOING,  ESE_READY_BORDING,  "ESE_WF_GUI_RB", u"车已到达请确认"),
#for driver
ESE_WF_GUI_CA:      (ESE_WF_ORDER,          ESS_CLOSED,         "ESE_WF_GUI_CA", u"确认可行性"),
ESE_WF_GUI_CD:      (ESE_ORDER_DONE,        ESS_NONE,           "ESE_WF_GUI_CD", u"等待确认订单"),
ESE_GOFOR_PICKUP:   (ESE_GOFOR_PICKUP,      ESE_GOFOR_PICKUP,   "ESE_GOFOR_PICKUP", u"接客途中"),
ESE_READY_PICKUP:   (ESE_READY_PICKUP,      ESE_READY_PICKUP,   "ESE_READY_PICKUP", u"准备接客"),
ESE_WF_GUI_BT:      (ESE_TRANSATION_GOING,  ESE_ORDER_DONE,     "ESE_WF_GUI_BT", u"等待交易开始"),
ESE_WF_GUI_ET:      (ESE_TRANSATION_DONE,   ESE_TRANSATION_DONE,"ESE_WF_GUI_ET", u"等待交易完成"),
ESE_READY_ET:       (ESE_READY_ET,          ESE_READY_ET,       "ESE_READY_ET",    u"抵达目的"),
ESE_READY_BT:       (ESE_READY_BT,          ESE_READY_BT,       "ESE_READY_BT",    u"准备开始交易"),
ESE_WFR_RB:         (ESE_TRANSATION_GOING,  ESE_READY_PICKUP,   "ESE_WFR_RB",    u"通知乘客中"),
#in common
#ESE_WF_GUI_UDS: (ESE_WF_GUI_UDS,        ESE_WF_GUI_UDS,"update driver status"), #notify the pos when current status is order_done, and the notify affects nothing
ESE_ORDER_DONE:         (ESS_NONE,          ESS_NONE,           "ESE_ORDER_DONE", u"预订成功"),    #handleConflict
ESE_TRANSATION_GOING:   (ESS_NONE,          ESS_NONE,           "ESE_TRANSATION_GOING", u"交易中"),
ESE_TRANSATION_DONE:    (ESS_CLOSED,        ESS_CLOSED,         "ESE_TRANSATION_DONE", u"交易结束")
}

EN_OK                       = 200
EN_SERVICENOTAVAILABLE      = 405
EN_CANCEL                   = 406
EN_REJECT                   = 407
EN_TIMEOUT                  = 408
EN_INVALIDUSERORPWD         = 414
EN_UNKNOWNERROR             = 444
EN_NETUNKNOWNNETEXCEPTION   = 460
EN_CONNECTEDALREADY         = 461
EN_DISCONNECTED             = 462
EN_CONNECTIMEOUT            = 463
EN_CONNECTCLOSED            = 464



retCodeMap = {

EN_OK                       : "ok",
EN_TIMEOUT                  : "response time out",
EN_SERVICENOTAVAILABLE      : "service not available",
EN_INVALIDUSERORPWD         : "invalid user or password",
EN_UNKNOWNERROR             : "unknown error",
EN_CANCEL                   : "canceled",
EN_REJECT                   : "driver reject the order"

}

TERMINATOR = "END_MC2CSP"

#notify subMethod
CSTR_CA         =   "checkAvailability"
CSTR_CO         =   "confirmOrder"
CSTR_CD         =   "confirmDriver"
CSTR_OC         =   "orderCancelled"
CSTR_UDS        =   "updateDriverStatus"
CSTR_TOGD       =   "timeoutToGetDriver"
CSTR_BT         =   "beginTransaction"
CSTR_ET         =   "endTransaction"
CSTR_GPS        =   "getPeerPosition"
CSTR_RB         =   "readyBording"
CSTR_CM         =   "comment"
translateMethod={
  CSTR_CA:u"确认是否可行",
  CSTR_CO:u"确认订单"  ,
  CSTR_CD:u"确认订单",
  CSTR_RB:u"车已到达请确认",
  CSTR_BT:u"确认交易开始",
  CSTR_ET:u"确认交易结束"             
                 }
#extraInfo key
CSTR2_GPS            =   "gpsInfo"
CSTR2_SESSION        =   "session"
CSTR2_PUBID          =   "pubID"
CSTR2_CSEQ           =   "cseq"
CSTR2_TIMEOUT        =   "timeout"
CSTR2_SERVICE        =   "service"

#param Dict for event
CSTR3_RETCODE        = "retCode"
CSTR3_EVENTCSEQ      = "eventCSeq"
CSTR3_REPORTER       = "reporter"
CSTR3_INFO           = "eventInfo"
CSTR3_METHOD         = "method"
CSTR3_SERVICE        = "service"
CSTR3_RESULT         = "result"

#special fields
CSTR3_ENABLEPOOLING  = "enablePooling"
CSTR3_POOLINGGROUP   = "poolingGroup"
CSTR3_POOLINGIDGROUP   = "poolingIDGroup"
notifyGUITable={
CSTR_CO:     ESE_WF_GUI_CO,
CSTR_CA:     ESE_WF_GUI_CA,
CSTR_CD:     ESE_WF_GUI_CD,
CSTR_TOGD:   ESE_WF_GUI_TOGD,
CSTR_BT:     ESE_WF_GUI_BT,
CSTR_ET:     ESE_WF_GUI_ET,
CSTR_RB:     ESE_WF_GUI_RB,
}
"""
Event mechanism is the interface between Peer ang GUI,
Above peer, there is the concrete event carrier, like SL4A,pygame,etc. 
"""
EVT_BENCH = 10000
#the following is for postEvent
EVT_WAITCONFIRM = (EVT_BENCH+1,"EVT_WAITCONFIRM")
EVT_GETLOCATION = (EVT_BENCH+2,"EVT_GETLOCATION")
#the following is for recvEvent
EVT2_BENCH = 20000
EVT2_CONFIRM       = (EVT2_BENCH+1,"EVT2_CONFIRM")
EVT2_SYNCRESULT    = (EVT2_BENCH+2,"EVT2_SYNCRESULT") #GUI return the result to peer
EVT2_PROXYFUNC     = (EVT2_BENCH+3,"EVT2_PROXYFUNC")  #delegate the function

itemPattern = re.compile(r"(\w+): ([^\r\n]+)")
def getItem(buf):
    m = itemPattern.search(buf)
    if m:
        return m.groups()
    else:
        raise Exception,"not found serviceItem%s"%buf

def getFieldStr(buf):
    return getItem(buf)[1]

def getFieldInt(buf):
    return int(getItem(buf)[1])

ipPattern = re.compile(r"([\.\w]+):(\d+)")
def getIP(buf):
    m = ipPattern.search(buf)
    if m:
        return m.group(1),int(m.group(2))
    else:
        raise Exception,"not found serviceItem%s"%buf

def getCurLocation():
    return (0,0,"iNeedTech Global Center")

def getTime(value):
     
     try:
         value = time.strptime(value,localtimeFmt)
         value = time.mktime(value)
         return int(value)
     except:
         self.log.exception("getTime fail%s"%value)

#locationPattern = re.compile(r"\w+:\s*\((\d+),\s*(\d+),\s*u*['\"](.+)['\"]")
locationPattern = re.compile(ur"\s*\((\d+),\s*(\d+),\s*u*['\"](.+)['\"]",re.U)
def getLocation(buf):
    m = locationPattern.search(buf)
    if m:
        return (int(m.group(1)),int(m.group(2)),m.group(3))
    else:
        raise Exception,"not found %s"%buf

pricePattern = re.compile(r"\s*\((\d+),\s*(\d+)\s*\)")
def getPrice(buf):
    m = pricePattern.search(buf)
    if m:
        return (int(m.group(1)),int(m.group(2)))
    else:
        raise Exception,"not found %s"%buf

def getDefaultMethodHead():

    buf  ="Location: (%d,%d,\"%s\")\r\n"%getCurLocation()
    buf +="Time: %s\r\n"%getLocalTime()

    return buf

def getDefaultTime():
    return "Time: %s\r\n"%getLocalTime()

retCodePattern  = re.compile(r"MC2CSP/1.0\D+(\d+) (.+)\r\n")

def getTheRetInfo(buf):
    m = retCodePattern.search(buf)
    if m:
        return (int(m.group(1)),m.group(2))
    else:
        raise Exception,"not found ret Info"

cseqPattern = re.compile(r"CSeq: (\d+)")
def getCSeq(buf):
    m = cseqPattern.search(buf)
    if m:
        return int(m.group(1))
    else:
        raise Exception,"not found CSeq"

sessionPattern =  re.compile(r"Session: (\d+)")
def getSession(buf):
    m = sessionPattern.search(buf)
    if m:
        return int(m.group(1))
    else:
        raise Exception,"not found Session ID"

def isOKResponse(retCode):
    return retCode>=200 and retCode <300


def getStrItem(dict1,key,value):
     
     dict1[key]= (value)
     
def getIntItem(dict1,key,value):
    
     dict1[key]= int(value)

def getLocationItem(dict1,key,value):
     x,y,address = getLocation(value)
     dict1["x"] = x
     dict1["y"] = y
     dict1["address"] = address
     
def getLocation2Item(dict1,key,value):
     x,y,address = getLocation(value)
     dict1["x2"] = x
     dict1["y2"] = y
     dict1["address2"] = address 

def getTimeItem(dict1,key,value):
    dict1[key]=getTime(value)

def getPriceRangeItem(dict1,key,value):
    pricelow,pricehigh = getPrice(value)
    dict1["pricelow"]   = pricelow
    dict1["pricehigh"]  = pricehigh 
       
ServiceFieldDict={
     "departureTime":               getTimeItem,
     "destinationTime":             getTimeItem,
     "nextTime":                    getTimeItem,
     "Time":                        getTimeItem, 
     "departureLocation" :          getLocationItem, 
     "Location" :                   getLocationItem,    
     "destinationLocation" :        getLocation2Item, 
     "priceRange":                  getPriceRangeItem,
     "status":                      getIntItem,
     "type":                        getIntItem,
     "score":                       getIntItem,
     "number":                      getIntItem,
     "distance":                    getIntItem,
     "pubID":                       getIntItem,
     "driverGender":                getIntItem,
     "passengerGender":             getIntItem,
     "refTime":                     getIntItem,
     "refFee":                      getIntItem,
     "timeout":                     getIntItem,
     "poolingID":                   getIntItem,
     "remainedSeats" :              getIntItem,
     "From":                        getStrItem   
}        
def parseServiceParams(serviceParamDict,strlist):

 for line in strlist:
    key,value=getItem(line)
    if ServiceFieldDict.has_key(key):
            ServiceFieldDict[key](serviceParamDict,key,value)
    else:
            serviceParamDict[key] = value
    

        
def parseLocationParams(locationParams,line1):
    
    if line1.find(":")>0:
        key,value=getItem(line1)
        if ServiceFieldDict.has_key(key):
            ServiceFieldDict[key](locationParams,key,value)
   
    return locationParams


def getServiceByDict(params):
    """
    Use the function to decouple the params's layout
    """
    return params[0]

def getServiceByList(params):
    return params[1]

def getLocationDict(params):
    return params[2]

def getMandotoryField(params):
    return params[3]

FLG_NORESPONSE = 1 #
NOResponseList=(CSTR_UDS,CSTR_BT,CSTR_ET,CSTR_OC,CSTR_CM)
def getSpecialFlag(method):
    flag = 0
    if method in NOResponseList:
        flag |= FLG_NORESPONSE
    return flag

#TIMEOUT setting


BASELINE_TIMEOUT = 60
MAX_ROUNDTRIP   = BASELINE_TIMEOUT/4
CA_TIMEOUT      = BASELINE_TIMEOUT
CA_UI_TIMEOUT   = CA_TIMEOUT - MAX_ROUNDTRIP #assume the max roundtrip is 20 seconds
CO_TIMEOUT      = BASELINE_TIMEOUT*2
CO_UI_TIMEOUT   = CO_TIMEOUT/2
CD_TIMEOUT      = CO_TIMEOUT/2
CD_UI_TIMEOUT   = CD_TIMEOUT - MAX_ROUNDTRIP
TOGD_TIMEOUT        = BASELINE_TIMEOUT
TOGD_UI_TIMEOUT     = TOGD_TIMEOUT - MAX_ROUNDTRIP
OC_TIMEOUT        = BASELINE_TIMEOUT
OC_UI_TIMEOUT     = OC_TIMEOUT - MAX_ROUNDTRIP
BT_TIMEOUT      = BASELINE_TIMEOUT
BT_UI_TIMEOUT   = BT_TIMEOUT - MAX_ROUNDTRIP
ET_TIMEOUT      = BASELINE_TIMEOUT
ET_UI_TIMEOUT   = ET_TIMEOUT - MAX_ROUNDTRIP
RB_TIMEOUT      = BASELINE_TIMEOUT
RB_UI_TIMEOUT   = RB_TIMEOUT - MAX_ROUNDTRIP
CENTER_LOG_PATH="E:/iNeedLog/"
DRIVER_LOG_PATH="E:/iNeedLog/driver/"
PASSENGER_LOG_PATH="E:/iNeedLog/passenger/"
PUBLISH_LOG_PATH="E:/iNeedLog/publish/"
genderC=[u"男",u"女"]
def getOriginalC(value):
    return str(value)

def getOriginalStr(value):
    return value

def getGenderC(value):
    return genderC[value]

def getRefTimeC(value):
    return u"%d"%((value+30)/60)+u"分钟"

def getRefFeeC(value):
    return u"%d "%value+u"元"


translateOrderList=(
           ("pubID",                u"订单号",getOriginalC),
           ("departureLocation",    u"出发地",getUStr),
           ("address",              u"出发地",getUStr),
           ("departureTime",        u"出发时间",getLocalTime),
           ("destinationLocation",  u"目的地",getUStr),
           ("address2",             u"目的地",getUStr),
           ("destinationTime",      u"预计抵达时间",getLocalTime),
          
           ("refFee",               u"参考费用",getRefFeeC),
           ("refTime",              u"参考时间",getRefTimeC),
           ("type",                 u"类型",   getOriginalC),
           ("number",               u"人数",   getOriginalC),
           ("timeout",              u"有效时间",getOriginalC),
           ("passengerID",          u"乘客电话",getUStr),
           ("passengerName",        u"乘客姓名",getUStr),
           ("passengerGender",      u"乘客性别",getGenderC),
           ("driverID",             u"司机电话",getUStr),
           ("driverName",           u"司机姓名",getUStr),
           ("driverGender",         u"司机性别",getGenderC),
           ("licenseID",            u"司机证件",getUStr),
           ("company",              u"公司",getUStr),
           ("carID",                u"车牌",getUStr),
           ("carBrand",             u"车型",getUStr),
           ("carColor",             u"颜色",getUStr),
           ("refRouting",           u"参考路线",getOriginalStr),
       )

def makeFieldFromDict(dict1):
    fields=""
    for key,value in dict1.items():
        fields += "%s: %s\r\n"%(key,value)
    return fields

def calculate2DLength(point1,point2):
    """
    use it to decide the length
    """
    return (point1[0]-point2[0])**2+(point1[1]-point2[1])**2

def cleanDataBaseForTest(db):#just for test
    db.execute("delete from order1")
    db.execute("delete from taxiservice")
    db.execute("delete from driverstatus")

INVALID_GRID    = -1 
INVALID_PUBID   = 0   

"""
publish status
"""
EPS_WAIT_CANDIDATES       = 0    #->no candidate, and wait for one    
EPS_CHECKAVAILABILITY     = 1    #->driver
EPS_CONFIRMORDER          = 2    #->passenger
EPS_CLOSED                = 3    #no matter done or fail, the task is closed

"""
long term service params
"""
ESP_TYPE            = 1
ESP_DEPART_TIME     = 2
ESP_DEPART_GRID     = 3
ESP_DEST_TIME       = 4
ESP_DEST_GRID       = 5
ESP_MATCHER         = 6
ESP_NUMBER          = 7
"""
Driver result
"""
EDR_DRIVERID        = 1
EDR_POOLINGID       = 2
EDR_POOLINGGROUP    = 3
EDR_DRIVER_GRID     = 4

"""
Driver status fields to indicates the ability
"""
EDS_NEXTTIME        = "nextTime"                    #TODO: better solution to change the active time of the driver
EDS_REMAINEDSEATS   = "remainedSeats"               #the number of available seats 
EDS_DESTLOCATION    = "destinationLocation"         #the dest of the order 
EDS_DESTTIME        = "destinationTime"
EDS_DEPARTLOCATION  = "departureLocation"           #the dest of the order 
EDS_DEPARTTIME      = "departureTime"
EDS_POOLINGID       = "poolingID"                   #work with orderDone,

"""
driver capability status
"""
EDC_ACTIVE      = 0 # active 
EDC_CLOSED      = 1 # should be removed

if __name__=="__main__":
    import os,sys,glob,re,subprocess,filecmp,time
    checkin_dir = "e:/kingcloud/ineed-taxi/code/iNeedProjectVC/iNeedProjectVC"
    checkin_comment = "0.5.1202.0900: fixed dead lock and refactoring the DC maintain"
    cmd = "svn ci \""+checkin_dir + "\" -m \"" + checkin_comment+ "\"";
    p = subprocess.Popen(cmd,stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
    print ''.join(p.stdout.readlines())




